package com.flow.framework.base.helper.i18n;

import com.flow.framework.base.properties.FrameworkBaseConfigProperties;
import com.flow.framework.base.properties.component.ResponseConfigProperties;
import com.flow.framework.base.service.i18n.Ii18nService;
import com.flow.framework.common.constant.FrameworkCommonConstant;
import com.flow.framework.common.util.random.RandomUtil;
import com.flow.framework.common.util.verify.VerifyUtil;
import com.flow.framework.core.constant.FrameworkCoreConstant;
import com.flow.framework.core.service.properties.ISystemConfigPropertiesService;
import com.flow.framework.core.system.listener.lifecycle.ISystemLifecycleListener;
import com.flow.framework.core.system.thread.pool.executor.ThreadPoolExecutor;
import com.flow.framework.core.system.thread.pool.policy.RejectedPolicy;
import com.flow.framework.core.system.thread.pool.task.BaseRunnable;
import com.flow.framework.core.util.ProxyUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.context.i18n.LocaleContextHolder;

import java.text.MessageFormat;
import java.util.List;
import java.util.Locale;

/**
 * 国际化辅助类
 *
 * @author luoguopiao
 * @version 0.0.1
 * @date 2022/12/10
 */
@Slf4j
@RequiredArgsConstructor
public class I18nHelper implements ISystemLifecycleListener {

    private static final ThreadPoolExecutor THREAD_POOL_EXECUTOR
            = new ThreadPoolExecutor(1, 2, 300,
            Integer.MAX_VALUE, "record-un-international-key", RejectedPolicy.DISCARD_POLICY);

    private final ISystemConfigPropertiesService systemConfigPropertiesService;

    private static ResponseConfigProperties responseConfigProperties;

    private static String appName;

    private static Ii18nService i18nService;

    /**
     * 获取给定key对应的国际化
     *
     * @param key    key
     * @param params params
     * @return
     */
    public static String getInternationalKey(String key, List<String> params) {
        if (VerifyUtil.isEmpty(key)
                || VerifyUtil.isEmpty(i18nService)
                || FrameworkCoreConstant.SUCCESS_CODE.equals(key)) {
            log.error("get international value error. key: {}", key);
            return responseConfigProperties.getI18nErrorDefaultMsg();
        }

        Locale locale = LocaleContextHolder.getLocale();

        // 返回的value如：xxxx{0}xxxxx{1}xxxxxx
        String internationalValue = i18nService.getInternationalValue(appName, key, locale);
        if (VerifyUtil.isEmpty(internationalValue)) {

            // 记录没有国际化的key
            recordUnInternationalKey(key, locale);
            log.error("get international value error. key: {}, locale: {}", key, locale.toString());
            return responseConfigProperties.getI18nErrorDefaultMsg();
        }
        if (null == params) {
            return internationalValue;
        }

        // 渲染是是按照{x}进行渲染的，其中x代表参数在数组的索引,如果参数为空，则返回原字符串
        return MessageFormat.format(internationalValue, params.toArray(new Object[0]));
    }

    private static void recordUnInternationalKey(String key, Locale locale) {
        if (VerifyUtil.isEmpty(i18nService)) {
            log.warn("record un-international key error. i18n is empty.");
            return;
        }
        try {
            String traceId = MDC.get(FrameworkCommonConstant.GLOBAL_LOG_TRACE_KEY);
            if (VerifyUtil.isEmpty(traceId)) {
                MDC.put(FrameworkCommonConstant.GLOBAL_LOG_TRACE_KEY, RandomUtil.random20LenId());
            }
            THREAD_POOL_EXECUTOR.submit(new BaseRunnable(60000) {
                @Override
                protected void execute() {
                    i18nService.recordUnInternationalKey(appName, key, locale);
                }
            });
        } catch (Exception e) {
            log.warn("record un-international key error. error: ", e);
        }
    }

    /**
     * @inheritDoc
     */
    @Override
    public void onStartUp() {
        appName = systemConfigPropertiesService.getConfigValue(FrameworkCoreConstant.SERVICE_NAME_KEY);
        i18nService = ProxyUtil.getProxied(Ii18nService.class);
        FrameworkBaseConfigProperties frameworkBaseConfigProperties = ProxyUtil.getProxied(FrameworkBaseConfigProperties.class);
        responseConfigProperties = frameworkBaseConfigProperties.getResponse();
    }

    /**
     * @inheritDoc
     */
    @Override
    public void onRefresh() {
        onStartUp();
    }
}
